如何区分渲染进程卡死和主进程阻塞?
考察点
- 多进程里“界面卡住”有两种根
- 用窗口数量和 CPU 归属把它们分开
参考答案
1. 现象不同
| 渲染进程卡死 | 主进程阻塞 | |
|---|---|---|
| 范围 | 通常一个窗口无响应,别的窗口还能点 | 所有窗口一起拖不动,托盘菜单也迟缓 |
| 事件 | 这个窗口触发 unresponsive | 往往没有单个窗口的 unresponsive,或全部一起触发 |
| CPU | 那个渲染进程 CPU 高,或内存涨到被杀 | 主进程 CPU 高,渲染进程在等 IPC |
| 常见原因 | 死循环、超大 JSON、同步布局 | 同步读大文件、同步数据库扫全表、sendSync 堆积 |
主进程是所有窗口的 IPC 枢纽。它一忙,每个 invoke 都在等,看起来像“每个页面都卡了”。
2. 怎么确认
const metrics = app.getAppMetrics();
// 看 type 为 Browser(主进程)还是 Tab(渲染进程),以及 cpu.percent
同时看是不是只有一个 webContents 进入了 unresponsive。
开发时主进程加 --inspect=9229,卡死时录 CPU profile。渲染进程用窗口里的 Performance 面板。profile 里如果主进程栈停在 fs.readFileSync 或 better-sqlite3,就不要去优化 React。
3. 处理方式也不同
渲染进程无响应:提示等待或 reload 这个窗口,草稿靠页面自己的本地暂存恢复。
主进程阻塞:reload 窗口没有用,因为新的 invoke 还是进同一个卡住的主进程。要把同步重活移走,并避免在 IPC handler 里做全表扫描。已经卡死的主进程只能等它回到事件循环,或者靠外部守护把整个应用重启。
4. 一条判断题
问自己:托盘右键菜单能不能马上弹出来?菜单在主进程。菜单都弹不出,就是主进程;菜单正常、只有页面不转,就是那个渲染进程。
面试话术
一个窗口无响应、别的窗口和托盘还正常,是渲染进程,看 unresponsive,必要时重载这一窗。所有窗口和托盘一起卡,是主进程堵住了事件循环,重载页面没用,要查同步 IO 和同步数据库,把重活放到 utilityProcess。用 getAppMetrics 看 CPU 在 Browser 还是 Tab 上。
常见追问
- GPU 进程卡死像哪一种? 画面花或停,但 JS 定时器可能还在。
render-process-gone的 reason 和 GPU 崩溃日志能分开。可以准备关闭硬件加速的启动参数做对照。 - invoke 一直不返回怎么查? 先看主进程 handler 有没有执行完。没执行到就是队列堵了;执行完没回到页面,再查渲染进程是不是已经重载、把这次 Promise 丢了。